package com.mls.logindemo.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.mls.logindemo.enums.ResultCodeEnum;
import com.mls.logindemo.exceptions.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
@Slf4j
public class TokenUtils {
    /**
     * token 加密Key 默认xtoad
     */
    @Value("${app.secretKey}")
    private static final String SECRET_KEY = "xtoad";
    /**
     * token 超时时间默认一个小时 单位ms
     */
    @Value("${app.tokenExpires}")
    private static final Long TOKEN_EXPIRES = 60 * 60 * 1000L;

    /**
     * BearerToken前缀
     */
    private static final String BEARER_TOKEN_PREFX = "Bearer ";
    /**
     * BasicToken前缀
     */
    private static final String BASIC_TOKEN_PREFX = "Basic ";
    /**
     * Token头名称
     */
    public static final String TOKEN_HEADER = HttpHeaders.AUTHORIZATION;
    /**
     * 签发key
     */
    private static final String CONTEXT_KEY_USER_ID = "userId";

    /**
     * 生成Token
     *
     * @param info 载荷信息
     * @return token串
     */
    public static String generateToken(Map<String, String> info) {
        Date start = new Date();
        // 一小时有效时间
        long currentTime = System.currentTimeMillis() + TOKEN_EXPIRES;
        Date end = new Date(currentTime);
        JWTCreator.Builder builder = JWT.create();
        builder.withAudience(info.get(CONTEXT_KEY_USER_ID));
        for (String key : info.keySet()) {
            builder.withClaim(key, info.get(key));
        }
        String token = builder.withIssuedAt(start)
                .withExpiresAt(end)
                .sign(Algorithm.HMAC256(SECRET_KEY));
        log.info("生成token成功，token：{}", token);
        return token;
    }

    /**
     * 取得请求Token中的签发对象
     *
     * @param token token
     * @return 结果
     * @throws Exception
     */
    public static List<String> getAudience(String token) {
        if (StringUtils.isEmpty(token)) {
            log.info("传入的Token为空");
            throw new BusinessException(ResultCodeEnum.EXPIRED_TOKEN);
        }
        if (token.startsWith(BEARER_TOKEN_PREFX)) {
            token = token.substring(BEARER_TOKEN_PREFX.length());
        } else if (token.startsWith(BASIC_TOKEN_PREFX)) {
            token = token.substring(BASIC_TOKEN_PREFX.length());
        }
        List<String> audience;
        try {
            audience = JWT.decode(token).getAudience();
        } catch (JWTDecodeException ex) {
            log.error("Token解码失败", ex);
            throw new BusinessException(ResultCodeEnum.EXPIRED_TOKEN);
        }
        return audience;
    }

    /**
     * 取得请求Token中全部载荷信息
     *
     * @param token token
     * @return 结果
     * @throws Exception
     */
    public static Map<String, Claim> getClaims(String token) {
        if (StringUtils.isEmpty(token)) {
            log.info("传入的Token为空");
            throw new BusinessException(ResultCodeEnum.EXPIRED_TOKEN);
        }
        if (token.startsWith(BEARER_TOKEN_PREFX)) {
            token = token.substring(BEARER_TOKEN_PREFX.length());
        } else if (token.startsWith(BASIC_TOKEN_PREFX)) {
            token = token.substring(BASIC_TOKEN_PREFX.length());
        }
        Map<String, Claim> claims;
        try {
            claims = JWT.decode(token).getClaims();
        } catch (JWTDecodeException ex) {
            log.error("Token解码失败", ex);
            throw new BusinessException(ResultCodeEnum.EXPIRED_TOKEN);
        }
        return claims;
    }

    /**
     * Token验证
     *
     * @param token token串
     * @return 验证结果
     */
    public static boolean verifyToken(String token) {
        if (StringUtils.isEmpty(token)) {
            log.error("传入的Token为空");
            return false;
        }
        if (token.startsWith(BEARER_TOKEN_PREFX)) {
            token = token.substring(BEARER_TOKEN_PREFX.length());
        } else if (token.startsWith(BASIC_TOKEN_PREFX)) {
            token = token.substring(BASIC_TOKEN_PREFX.length());
        }
        // 验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET_KEY)).build();
        try {
            jwtVerifier.verify(token);
        } catch (TokenExpiredException ex) {
            log.error("Token验证失败，Token已经过期", ex);
            return false;
        } catch (JWTVerificationException ex) {
            log.error("Token验证失败", ex);
            return false;
        } catch (Exception ex) {
            log.error("Token验证失败", ex);
            return false;
        }

        return true;
    }

}